import 'package:build/build.dart';
import 'package:code_builder/code_builder.dart';
import 'package:froom_generator/value_object/dao.dart';
import 'package:froom_generator/value_object/deletion_method.dart';
import 'package:froom_generator/value_object/entity.dart';
import 'package:froom_generator/value_object/insertion_method.dart';
import 'package:froom_generator/value_object/query_method.dart';
import 'package:froom_generator/value_object/transaction_method.dart';
import 'package:froom_generator/value_object/update_method.dart';
import 'package:froom_generator/writer/deletion_method_writer.dart';
import 'package:froom_generator/writer/insertion_method_writer.dart';
import 'package:froom_generator/writer/transaction_method_writer.dart';
import 'package:froom_generator/writer/update_method_writer.dart';
import 'fall_query_method_writer.dart';
import 'package:fall_gen_base/fall_gen_base.dart';
import 'package:fall_core_base/fall_core_base.dart';
import 'package:logger/logger.dart';

/// Fall Data 项目专用的 DAO 代码生成器
/// 使用 ClassBuilder 和 MethodBuilder 生成代码，而不是 StringBuffer
class FallDaoWriter {
  final Dao dao;
  final Entity entity;
  final BuildStep step;
  const FallDaoWriter(this.dao, this.entity, this.step);

  /// 生成完整的 DAO 实现代码
  String write() {
    final daoName = dao.name;
    final entityName = entity.classElement.displayName;

    // 创建库构建器
    final library = LibraryBuilder();

    // 添加导入语句
    library.directives.addAll(_generateImports());

    // 添加类注释
    final classBuilder = ClassBuilder()
      ..name = '${daoName}Impl'
      ..extend = refer(daoName)
      ..docs.addAll([
        '/// $entityName DAO实现',
      ]);
    _generateField(classBuilder);
    // 添加构造器
    classBuilder
      ..constructors.add(_generateConstructor(daoName, entityName))
      ..methods.addAll(_generateQueryMethods(dao.queryMethods))
      ..methods.addAll(_generateInsertionMethods(dao.insertionMethods))
      ..methods.addAll(_generateUpdateMethods(dao.updateMethods))
      ..methods.addAll(_generateDeletionMethods(dao.deletionMethods))
      ..methods.addAll(_generateTransactionMethods(dao.transactionMethods));

    // 将类添加到库
    library.body.add(classBuilder.build());

    // 生成代码并格式化
    final emitter = DartEmitter();
    return library.build().accept(emitter).toString();
  }

  void _generateField(ClassBuilder classBuilder) {
    // classBuilder
    //   ..fields.add(Field((builder) => builder
    //     ..modifier = FieldModifier.final$
    //     ..name = '_queryAdapter'
    //     ..assignment = Code('queryAdapter')
    //     ..type = refer('QueryAdapter')));
  }

  /// 生成导入语句
  List<Directive> _generateImports() {
    final imports = <Directive>[];
    // imports.add(Directive.import('package:froom/froom.dart'));
    LogUtil.d('生成导入路径: ${step.inputId.uri.toString()}');
    imports.add(Directive.import(GenUtil.getImportPath(
      step.inputId.uri,
      step.inputId.changeExtension(".g.dart").uri,
    )));
    LogUtil.d(
        '实体库路径: ${entity.classElement.library.uri.toString()}---${step.inputId.changeExtension(".g.dart").uri.toString()}');
    imports.add(Directive.import(GenUtil.getImportPath(
      entity.classElement.library.uri,
      step.inputId.changeExtension(".g.dart").uri,
    )));
    return imports;
  }

  /// 生成构造器
  Constructor _generateConstructor(String daoName, String entityName) {
    return Constructor((builder) => builder
      ..requiredParameters.addAll([
        Parameter((p) => p..name = 'database'),
        Parameter((p) => p..name = 'changeListener'),
      ])
      ..initializers.add(Code('''super(
            database,
            changeListener,
            $entityName.getTableName(),
            $entityName.getPrimaryKey(),
            $entityName.toMap,
            $entityName.toEntity,
            $entityName.getFieldCol())''')));
  }

  List<Method> _generateInsertionMethods(
    final List<InsertionMethod> insertionMethods,
  ) {
    return insertionMethods
        .map((method) => InsertionMethodWriter(method).write())
        .toList();
  }

  List<Method> _generateUpdateMethods(
    final List<UpdateMethod> updateMethods,
  ) {
    return updateMethods
        .map((method) => UpdateMethodWriter(method).write())
        .toList();
  }

  List<Method> _generateDeletionMethods(
    final List<DeletionMethod> deletionMethods,
  ) {
    return deletionMethods
        .map((method) => DeletionMethodWriter(method).write())
        .toList();
  }

  List<Method> _generateQueryMethods(final List<QueryMethod> queryMethods) {
    return queryMethods
        .map((method) => FallQueryMethodWriter(method).write())
        .toList();
  }

  List<Method> _generateTransactionMethods(
    final List<TransactionMethod> transactionMethods,
  ) {
    return transactionMethods
        .map((method) => TransactionMethodWriter(method).write())
        .toList();
  }
}
